import { TMakeASTNode, CompilerError } from './types';

export class TMakeLexer {
  private input: string;
  private position: number = 0;
  private line: number = 1;
  private column: number = 1;
  private errors: CompilerError[] = [];

  constructor(input: string) {
    this.input = input;
  }

  public getErrors(): CompilerError[] {
    return this.errors;
  }

  private isWhitespace(char: string): boolean {
    return /\s/.test(char);
  }

  private isDigit(char: string): boolean {
    return /[0-9]/.test(char);
  }

  private isAlpha(char: string): boolean {
    return /[a-zA-Z_\u4e00-\u9fa5]/.test(char);
  }

  private peek(offset: number = 0): string {
    return this.input[this.position + offset] || '';
  }

  private consume(): string {
    if (this.position >= this.input.length) {
      return '';
    }
    
    const char = this.input[this.position++];
    if (char === '\n') {
      this.line++;
      this.column = 1;
    } else {
      this.column++;
    }
    return char;
  }

  private skipWhitespace(): void {
    while (this.position < this.input.length && this.isWhitespace(this.peek())) {
      this.consume();
    }
  }

  /**
   * 跳过注释
   * 支持多行注释 
   */
  private skipComment(): void {
    // 处理单行注释 //
    if (this.peek() === '/' && this.peek(1) === '/') {
      while (this.position < this.input.length && this.peek() !== '\n') {
        this.consume();
      }
    }
    // 处理多行注释 /* */
    else if (this.peek() === '/' && this.peek(1) === '*') {
      this.consume();
      this.consume();
      
      while (this.position < this.input.length) {
        if (this.peek() === '*' && this.peek(1) === '/') {
          this.consume();
          this.consume();
          break;
        }
        this.consume();
      }
    }
  }

  /**
   * 读取字符串字面量
   * 支持转义字符处理
   * @returns 解析出的字符串内容
   */
  private readString(): string {
    const quote = this.consume();
    let value = '';
    let escaped = false;
    
    while (this.position < this.input.length) {
      const char = this.peek();
      
      if (char === '') {
        this.errors.push({
          type: 'lexical',
          message: `未终止的字符串字面量`,
          line: this.line,
          column: this.column,
          token: value
        });
        break;
      }
      
      if (escaped) {
        value += this.consume();
        escaped = false;
      } else if (char === '\\') {
        this.consume();
        escaped = true;
      } else if (char === quote) {
        this.consume();
        break;
      } else {
        value += this.consume();
      }
    }
    
    return value;
  }

  /**
   * 读取标识符
   * 标识符由字母、数字、下划线或中文组成，必须以字母、下划线或中文开头
   * @returns 解析出的标识符
   */
  private readIdentifier(): string {
    let value = '';
    while (this.position < this.input.length && 
           (this.isAlpha(this.peek()) || this.isDigit(this.peek()) || this.peek() === '.')) {
      value += this.consume();
    }
    return value;
  }

  /**
   * 读取数字字面量
   * 支持整数和小数
   * @returns 解析出的数字字符串
   */
  private readNumber(): string {
    let value = '';
    let hasDot = false;
    
    while (this.position < this.input.length && 
           (this.isDigit(this.peek()) || (!hasDot && this.peek() === '.'))) {
      if (this.peek() === '.') {
        hasDot = true;
      }
      value += this.consume();
    }
    
    if (value.endsWith('.') || (value.includes('.') && value.split('.')[1] === '')) {
      this.errors.push({
        type: 'lexical',
        message: `无效的数字格式: ${value}`,
        line: this.line,
        column: this.column,
        token: value
      });
    }
    
    return value;
  }

  /**
   * 将源代码文本转换为标记序列
   * @returns 包含标记数组和错误数组的对象
   */
  public tokenize(): { tokens: TMakeASTNode[], errors: CompilerError[] } {
    const tokens: TMakeASTNode[] = [];
    
    // 遍历输入文本，生成标记
    while (this.position < this.input.length) {
      this.skipWhitespace();
      
      if (this.position >= this.input.length) break;
      
      const char = this.peek();
      
      // 检查并跳过注释
      if (char === '/' && (this.peek(1) === '/' || this.peek(1) === '*')) {
        this.skipComment();
        continue;
      }
      
      // 处理字符串字面量
      if (char === '"' || char === "'") {
        const value = this.readString();
        tokens.push({
          type: 'string',
          value,
          line: this.line,
          column: this.column
        });
      }
      // 处理数字字面量
      else if (this.isDigit(char)) {
        const value = this.readNumber();
        tokens.push({
          type: 'number',
          value,
          line: this.line,
          column: this.column
        });
      }
      // 处理标识符
      else if (this.isAlpha(char)) {
        const value = this.readIdentifier();
        
        // 检查是否为关键词，包括中文关键词
        const keywords = ['假如', '是', '否则', '结束', '如果', '循环', '函数', '返回', 'TMake版本', '设置变量'];
        if (keywords.includes(value)) {
          tokens.push({
            type: 'keyword',
            value,
            line: this.line,
            column: this.column
          });
        } else {
          tokens.push({
            type: 'identifier',
            value,
            line: this.line,
            column: this.column
          });
        }
      }
      // 处理标点符号
      else if ('();,[]{}='.includes(char)) {
        tokens.push({
          type: 'punctuation',
          value: this.consume(),
          line: this.line,
          column: this.column
        });
      }
      // 处理未知字符
      else {
        const unknownChar = this.consume();
        this.errors.push({
          type: 'lexical',
          message: `无法识别的字符: '${unknownChar}'`,
          line: this.line,
          column: this.column,
          token: unknownChar
        });
      }
    }
    
    return { tokens, errors: this.errors };
  }
}